# Written by koya
# -*- coding:utf-8 -*-
# file: run_game.py
#
from OpenGL.GL import *
#from OpenGL.GLUT import *
from OpenGL.GLU import *

import sys,random
import pygame
from pygame.locals import *

import tunnels,waterripples,maths
import image, font, particles, gui

import menu


tunnel = tunnels.tunnel_obj()


class opengl_window( object ):
    def __init__( self, clock, width = 640, height = 480 ):  # 初始化

        self.width = width
        self.height = height
        


        self.clock = clock

        

        self.menu = gui.mainmenu_obj( 0.4, [ 0.0, 0.0, 0] )
        self.menu_pos = 32
        self.selected_menuitem_pos = 32

        #选中菜单之后,运行完效果,才进入选中的内容
        self.is_run_to_next = False

        #Scissor效果
        self.first_run = True
        self.h1_scissor = float(self.height / 2.0)
        self.h2_scissor = 0.0

        self.last_time = 0.0

        #纹理偏移 (主要是'About'菜单需要的效果)
        self.alias_texcrood =  1.0
       
        self.init_gl(width, height)                  # 调用OpenGL初始化函数

       
        self.smallFont = font.Font("Hemi Head 426.TTF", 20)
       
    def draw(self):                                 # 绘制场景

  
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )        # 清除屏幕
        
        # 第一次运行的效果
        if self.first_run:
            if self.h1_scissor >= 5:
                self.h1_scissor -= 5
                self.h2_scissor += 10
            else:
                self.h1_scissor = 0.0
                self.h2_scissor = float( self.height )
                self.first_run = False


        glEnable(GL_SCISSOR_TEST)
        glScissor(0	,int( self.h1_scissor ),512,int( self.h2_scissor ))
        
        glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR)
        glEnable(GL_BLEND)
        
        # 显示界面上的帮助信息
        #self.show_mainmenu_help_info()
        
        # 投影
        glLoadIdentity()                            
        self.resize_gl_scene()
       
        #绘制天空盒
        glLoadIdentity()
        self.cubebox()
       
        # 绘制隧道
        tunnel.render( self.tunnel_texid )   

        if self.first_run:
            #glDisable( GL_SCISSOR_TEST )
            pygame.display.flip()
            return 
        
        glLoadIdentity()

        tunnels_posmin = tunnel.get_tunnel_info( 0, int(self.menu_pos) )
        tunnels_posmax = tunnel.get_tunnel_info( 6, int(self.menu_pos) )
        
        glTranslatef( (tunnels_posmin.x + tunnels_posmax.x)*0.5, \
                     (tunnels_posmin.y + tunnels_posmax.y)*0.5, \
                     (tunnels_posmin.z + tunnels_posmax.z)*0.5 )
 
        if self.menu.is_run_effect():

            pos_min = tunnel.get_tunnel_info( 0, int(self.selected_menuitem_pos) )
            pos_max = tunnel.get_tunnel_info( 6, int(self.selected_menuitem_pos) )
            self.menu.set_selected_menuitem_pos( (pos_min.x + pos_max.x)*0.5, \
                     (pos_min.y + pos_max.y)*0.5, \
                     (pos_min.z + pos_max.z)*0.5   )

            if self.selected_menuitem_pos <= 31:
                
                self.selected_menuitem_pos += 0.5
                self.is_run_to_next = False

            else:

                self.is_run_to_next = True

        else: 
            self.selected_menuitem_pos = self.menu_pos

        #if self.selected_menuitem_pos <= 31:
        self.menu.render_menu()

        if self.menu_pos >= 3:
            self.menu_pos -= 0.5

        

        # 判断是否有菜单项被选中,并且得到该菜单项
        is_selected, selected_menuitem = self.menu.get_selected_menuitem()

        if is_selected and self.is_run_to_next:

            if self.h1_scissor <= self.height*0.5 - 5:

                     self.h1_scissor += 5
                     self.h2_scissor -= 10


            else:
                self.h1_scissor = float( self.height * 0.5 )
                self.h2_scissor = 0.0
                
                #glClearColor( 1,1,1,1)
                glDisable( GL_BLEND )
                glDisable( GL_DEPTH_TEST )
                glDisable( GL_SCISSOR_TEST )
                glDisable( GL_TEXTURE_2D )
                glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
                glLoadIdentity()
                self.resize_gl_scene()


                # 开始游戏
                if selected_menuitem is 'Play':
                    
                    screen = pygame.display.set_mode( (512,640) )

                    #游戏初始化,以及游戏循环  
                    menu.menu( screen )

                    self.reset()
                    return               
                               
                        
                # 继续游戏 直接读取上次的游戏记录
                if selected_menuitem is 'Continue':
                    pass

                # 设置游戏
                if selected_menuitem is 'Options':
                    
                    
                    options_menu = gui.options_menu_obj( font.load_font( "Hemi Head 426.TTF", 20 ) )
                    #smallFont = font.Font("Hemi Head 426.TTF", 20)

                    particle_system = particles.particle_system_obj( 100, 2 )
                    
                    while True: 
                        glClearColor( 0, 0, 0, 1 )
                        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
                        glLoadIdentity()
                        self.resize_gl_scene()

                        glTranslatef( 0, 0, -50 )
                        
                        glDepthMask( GL_FALSE )
                        glEnable ( GL_TEXTURE_2D )

                        
                        glBlendFunc(GL_ONE,GL_ONE)
                        glEnable( GL_BLEND )
             
                        particle_system.render()

                        glMatrixMode(GL_PROJECTION)
                        glPushMatrix()
                        glLoadIdentity();
                        glOrtho( 0, self.width, self.height, 0, -100.0,100.0 )
                        glMatrixMode(GL_MODELVIEW)
                        glPushMatrix()
                        glLoadIdentity()
                        
                        #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
                        
                        #self.smallFont.draw("Use 'Esc' back to MainMenu",pos=(10, 590))
                        
                        glColor4f(0,0,0,1)
                        glBlendFunc( GL_ONE, GL_ONE )
                        options_menu.render()
                        glColor4f(1,1,1,1)
                        self.view_perspective()
 
                        
                          
                        
                        
                        glDepthMask( GL_TRUE )
                        glDisable( GL_TEXTURE_2D )
                        glDisable( GL_BLEND )
                        pygame.display.flip()

                        keystate = pygame.key.get_pressed()
                        for event in pygame.event.get():

                           if event.type == QUIT:
                                pygame.quit()
                                sys.exit()

                           if keystate[K_ESCAPE]:
                                # 返回到主菜单 需要重置的, 
                                # 包括self.h1_scissor, self.h2_scissor, self.menu.reset 
                                self.reset()
                                return  
                    
                 

                # 关于游戏
                if selected_menuitem is 'About':

                    while True:

                        self.render_water_ripple()
                        
                        keystate = pygame.key.get_pressed()
                        for event in pygame.event.get():

                           if event.type == QUIT:
                                pygame.quit()
                                sys.exit()

                           if keystate[K_ESCAPE]:
                                # 返回到主菜单 需要重置的, 
                                # 包括self.h1_scissor, self.h2_scissor, self.menu.reset 
                                self.reset()
                                return  
                        
                    
                # 退出游戏
                if selected_menuitem is 'Exit':
                    pygame.quit()
                    sys.exit(0)



        glDisable( GL_SCISSOR_TEST )
        pygame.display.flip()
        #glutSwapBuffers()                     # 交换缓存

    def reset( self ):

        pygame.display.set_mode( ( self.width, self.height ), OPENGL | DOUBLEBUF )

        self.init_gl( self.width, self.height )

        self.menu = gui.mainmenu_obj( 0.4, [ 0.0, 0.0, 0] )
        self.menu_pos = 32
        self.selected_menuitem_pos = 32

        self.first_run = True
        self.h1_scissor = float(self.height * 0.5)
        self.h2_scissor = 0.0

        self.last_time = 0.0

        #纹理偏移
        self.alias_texcrood =  1.0

        self.menu.reset()

    def render_water_ripple( self ):
        

        self.water_ripple.create_raindrop( random.randrange( 10, 50 ), random.randrange( 10, 50 ), 1060 )
       
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
        
        glDisable( GL_SCISSOR_TEST )
        glLoadIdentity()
        self.resize_gl_scene()

        glTranslatef(0.0,0.0,-200)

        glDepthMask(GL_FALSE)

        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_COLOR, GL_ONE)
        glColor4f(1,1,1,1)
                
        glEnable(GL_TEXTURE_2D)
        glBindTexture(GL_TEXTURE_2D,self.water_texid)
                    
        glEnable(GL_TEXTURE_GEN_S)
        glEnable(GL_TEXTURE_GEN_T)
        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP)
        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP)

        glPushMatrix()
        glRotatef(90,1,0,0)
        self.water_ripple.draw_water()

        glPopMatrix()
                    
        glDisable(GL_TEXTURE_GEN_S)
        glDisable(GL_TEXTURE_GEN_T)

        
        self.window_scale *= 160

        glColor4f(1,1,1,1)
        glBindTexture( GL_TEXTURE_2D, self.introduce_texid )
        glBegin(GL_QUADS)
        glTexCoord2f(0.0, self.alias_texcrood )
        glVertex3f(- self.window_scale, 160, 0)
        glTexCoord2f(0.0, self.alias_texcrood - 0.5)
        glVertex3f(- self.window_scale,-160, 0)
        glTexCoord2f(1.0, self.alias_texcrood - 0.5)
        glVertex3f(self.window_scale, -160, 0)
        glTexCoord2f(1.0, self.alias_texcrood )
        glVertex3f(self.window_scale, 160, 0)
        glEnd()

        if self.alias_texcrood > 0.5:
            self.alias_texcrood -= 0.001
        else:
            self.alias_texcrood = 1.0



        glDisable(GL_TEXTURE_2D)
        glDisable( GL_BLEND )
        glDepthMask(GL_TRUE)

        pygame.display.flip()

    def show_mainmenu_help_info( self ):

        glDepthMask( GL_FALSE )
        
        glBlendFunc(GL_ONE,GL_ONE)
        glEnable( GL_BLEND )
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()
        glLoadIdentity();
        glOrtho( 0, self.width, self.height, 0, -100.0,100.0 )
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadIdentity()

        glEnable( GL_TEXTURE_2D )

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        self.smallFont.draw("Use 'Enter' to choose",pos=(10, 10))
        self.smallFont.draw("Use 'LEFT' and 'RIGHT' to rotate",pos=(10, 30))
        self.smallFont.draw("Use 'Esc' back to MainMenu",pos=(10, 50))


        is_selected, selected_menuitem = self.menu.get_selected_menuitem()
        self.smallFont.draw("%s"%selected_menuitem,pos=(220, 500))

        glDisable( GL_TEXTURE_2D )
        glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR)
        self.view_perspective()

        glDepthMask( GL_TRUE )


       
    def init_gl( self, width, height ):                    # OpenGL初始化函数

        glShadeModel(GL_SMOOTH)                     # 启动平滑阴影
        glClearColor(0.0, 0.0, 0.0, 1.0)                # 设为黑色背景 
        glClearDepth(1.0)                       # 设置深度缓存
        glDepthFunc(GL_LEQUAL)                        # 设置深度测试类型
        glEnable(GL_DEPTH_TEST)                     # 允许深度测试
        glEnable(GL_POINT_SMOOTH)
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
         

        #initial
        
        self.cubeface0 = image.load_texture2("data/skybox/lobbyxpos.bmp")
        self.cubeface1 = image.load_texture2("data/skybox/lobbyxneg.bmp")
        self.cubeface2 = image.load_texture2("data/skybox/lobbyypos.bmp")
        self.cubeface3 = image.load_texture2("data/skybox/lobbyyneg.bmp")
        self.cubeface4 = image.load_texture2("data/skybox/lobbyzpos.bmp")
        self.cubeface5 = image.load_texture2("data/skybox/lobbyzneg.bmp" )
        
        self.tunnel_texid = image.load_texture2("data/tunnels/tunnel.bmp" )

        #水波效果
        self.water_texid = image.load_texture2( "data/water/WaterBump.jpg")
        self.water_ripple = waterripples.water_ripple_obj( 60, 60, 0.66 )

        self.introduce_texid = image.load_texture2("data/introduce.jpg")
        
        self.window_scale = float( self.width ) / float( self.height ) 
        
    def resize_gl_scene(self):

        if self.height == 0:
            self.height = 1
        glViewport(0,0,self.width,self.height)
        glMatrixMode(GL_PROJECTION)                 # 设置观察矩阵
        glLoadIdentity()                            # 重置观察矩阵
        gluPerspective(90.0, float(self.width)/float(self.height), 0.1, 9999.0)   # 计算屏幕高宽比
        glMatrixMode(GL_MODELVIEW)                  # 设置观察矩阵
        glLoadIdentity()
        
        #gluLookAt(0,0,1,0,0,0,0,1,0)        

    def view_ortho(self):
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()
        glLoadIdentity();
        glOrtho(-100,100,-100,100,-100.0,100.0)
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadIdentity()
    def view_perspective(self):
        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)
        glPopMatrix()
    def cubebox( self ):


        glDisable(GL_LIGHTING);
        glColor4f(1.0, 1.0, 1.0,1.0);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, self.cubeface0);
        glBegin(GL_QUADS);
        glNormal3f( -1.0, 0.0, 0.0);
        glTexCoord2f(0.005, 0.995); glVertex3i(1000, 1000, 1000);
        glTexCoord2f(0.005, 0.005); glVertex3i(1000, -1000, 1000);
        glTexCoord2f(0.995, 0.005); glVertex3i(1000, -1000, -1000);
        glTexCoord2f(0.995, 0.995); glVertex3i(1000, 1000, -1000);
        glEnd();
        
        glBindTexture(GL_TEXTURE_2D, self.cubeface1);
        glBegin(GL_QUADS);
        glNormal3f( 1.0, 0.0, 0.0);
        glTexCoord2f(0.005, 0.995); glVertex3i(-1000, 1000, -1000);
        glTexCoord2f(0.005, 0.005); glVertex3i(-1000, -1000, -1000);
        glTexCoord2f(0.995, 0.005); glVertex3i(-1000, -1000, 1000);
        glTexCoord2f(0.995, 0.995); glVertex3i(-1000, 1000, 1000);
        glEnd();
        
        glBindTexture(GL_TEXTURE_2D, self.cubeface2);
        glBegin(GL_QUADS);
        glNormal3f( 0.0, -1.0, 0.0);
        glTexCoord2f(0.005, 0.995); glVertex3i(-1000, 1000, -1000);
        glTexCoord2f(0.005, 0.005); glVertex3i(-1000, 1000, 1000);
        glTexCoord2f(0.995, 0.005); glVertex3i(1000, 1000,1000);
        glTexCoord2f(0.995, 0.995); glVertex3i(1000, 1000, -1000);
        glEnd();
        
        glBindTexture(GL_TEXTURE_2D, self.cubeface3);
        glBegin(GL_QUADS);
        glNormal3f( 0.0, 1.0, 0.0);
        glTexCoord2f(0.005, 0.995); glVertex3i(-1000, -1000, 1000);
        glTexCoord2f(0.005, 0.005); glVertex3i(-1000, -1000, -1000);
        glTexCoord2f(0.995, 0.005); glVertex3i(1000, -1000,-1000);
        glTexCoord2f(0.995, 0.995); glVertex3i(1000, -1000, 1000);
        glEnd();
        
        glBindTexture(GL_TEXTURE_2D, self.cubeface4);
        glBegin(GL_QUADS);
        glNormal3f( 0.0, 0.0, -1.0);
        glTexCoord2f(0.005, 0.995); glVertex3i(-1000, 1000, 1000);
        glTexCoord2f(0.005, 0.005); glVertex3i(-1000,-1000, 1000);
        glTexCoord2f(0.995, 0.005); glVertex3i(1000, -1000, 1000);
        glTexCoord2f(0.995, 0.995); glVertex3i(1000, 1000, 1000);
        glEnd();
        
        glBindTexture(GL_TEXTURE_2D, self.cubeface5);
        glBegin(GL_QUADS);
        glNormal3f( 0.0, 0.0, 1.0);
        glTexCoord2f(0.005, 0.995); glVertex3i(1000, 1000, -1000);
        glTexCoord2f(0.005, 0.005); glVertex3i(1000, -1000, -1000);
        glTexCoord2f(0.995, 0.005); glVertex3i(-1000,  -1000, -1000);
        glTexCoord2f(0.995, 0.995); glVertex3i(-1000,  1000, -1000);
        glEnd();
        glDisable(GL_TEXTURE_2D)

    def draw_quads(self, neg_x, pos_x, neg_y, pos_y ):
        glTexCoord2f(0.0, 1.0 )
        glVertex3f(neg_x, pos_y, 0)
        glTexCoord2f(0.0, 0.0)
        glVertex3f(neg_x, neg_y, 0)
        glTexCoord2f(1.0, 0.0)
        glVertex3f(pos_x, neg_y, 0)
        glTexCoord2f(1.0, 1.0 )
        glVertex3f(pos_x, pos_y, 0)
        glEnd() 

    def get_input( self ):
        
        global CameraPos, CameraRotate

        
        keystate = pygame.key.get_pressed()
        mrel = pygame.mouse.get_rel()
        mpress = pygame.mouse.get_pressed()
        for event in pygame.event.get():

            if event.type == QUIT or keystate[K_ESCAPE]:
                pygame.quit()
                sys.exit()

            if keystate[K_SPACE]:
                self.water_ripple.create_raindrop( 20, 20, 1060 );

            #if keystate[K_RETURN]:
                #pass
                #self.selected_menuitem_pos = 0.0
                #self.menu.reset()
      

        
def main():

    
    
    pygame.init()
    Screen = (512,640)
    pygame.display.set_caption( 'Mini Project' )
    pygame.display.gl_set_attribute(pygame.GL_ALPHA_SIZE, 8)

    screen = pygame.display.set_mode( Screen, OPENGL | DOUBLEBUF )
    
    clock = pygame.time.Clock()

    window = opengl_window( clock, 512, 640 )   # 创建窗口
    #window.MainLoop()                              # 进入消息循环

    
    millis = 0
    while True:

        #clock.tick(100)
        #print clock.get_fps()
        pygame.event.pump()

        #font = pygame.font.Font( "data//Hemi Head 426.TTF", 20 )
        #image = font.render(" I/'m koya!!!!!!!!!!!!!!!! ", 0, ( 255, 0, 0 ) ).convert()
        #pygame.display.get_surface().blit( image, [100,100])

        tick = clock.tick()
        millis += tick
        if millis > 1000:

            sys.stdout.write('FPS %05d\r' % clock.get_fps())
            sys.stdout.flush()
            millis = 0

        window.get_input()
        window.draw()

        
        

if __name__=='__main__':main()
